package com.rivues.util.service.system;

import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;

import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.rivues.core.RivuDataContext;
import com.rivues.module.platform.web.model.Cube;
import com.rivues.module.platform.web.model.JobDetail;
import com.rivues.module.platform.web.model.warning.EventBean;
import com.rivues.util.local.LocalTools;
import com.rivues.util.service.monitor.BusinessService;
import com.rivues.util.tools.CronTools;
import com.rivues.util.tools.RuntimeData;

@Component
public class JobDetailService extends BusinessService{
	private static Logger log = LoggerFactory.getLogger(JobDetailService.class) ;
	private static boolean taskRunning = false ;
	@SuppressWarnings("unchecked")
	@Scheduled(fixedRate = 1000*5)  
	public void service(){
		if (RivuDataContext.isStart() && !RivuDataContext.isStopping() && !taskRunning) {
			try{
				taskRunning = true ; 
				/**
				 * 将JobDetail加入到执行列表中，按照执行时间和优先级排序
				 */
				Map<String, Object> jobDetailMap = RivuDataContext.getClusterInstance().get(RivuDataContext.DistributeEventEnum.JOBDETAIL.toString());
				Map<String, Object> runningJobMap = RivuDataContext.getClusterInstance().get(RivuDataContext.DistributeEventEnum.RUNNINGJOB.toString());
				/**
				 * 遍历RuninigJob，发现其中有任务被执行了停止任务的 指令
				 */
				Iterator<String> disRunningJobIterator = runningJobMap.keySet().iterator() ;
				while(disRunningJobIterator.hasNext()){
					String jobId = disRunningJobIterator.next() ;
					if(runningJobMap.get(jobId)!=null){
						JobDetail runningJob = (JobDetail) runningJobMap.get(jobId) ;
						if(RivuDataContext.getLocalRunningJob().get(jobId)!=null){
							JobDetail localRuninigJob = RivuDataContext.getLocalRunningJob().get(jobId) ;
							localRuninigJob.setFetcher(runningJob.isFetcher()) ;
							localRuninigJob.setPause(runningJob.isPause()) ;
						}
					}
				}
				
				int page = 0 ;
				/**
				 * 任务执行 条件 （plantask为true，即是后台执行任务）， 
				 * 		a：任务的状态是 1，即手动提交执行的任务
				 * 		b：任务的执行时间 为将来的 5秒 
				 * 		c：任务的执行时间> 当前时间 -5秒
				 */
				List<JobDetail> jobDetailList  = RivuDataContext.getService().findPageByCriteria(DetachedCriteria.forClass(JobDetail.class).add(Restrictions.or(Restrictions.eq("taskstatus", "1"), Restrictions.or(Restrictions.ne("taskstatus", "0"), Restrictions.and(Restrictions.eq("plantask", true), Restrictions.lt("nextfiretime", new Date(System.currentTimeMillis()+5*1000)))))), 100, page++) ;
				for(JobDetail jobDetail : jobDetailList){
					/**
					 * 任务已在 等待或执行队列
					 */
					if(jobDetailMap.get(jobDetail.getId())==null && runningJobMap.get(jobDetail.getId())==null){
						
						if(jobDetail.getTasktype()!=null && jobDetail.getTasktype().equals(RivuDataContext.TaskTypeEnum.EXPORT.toString())){
							/**
							 * 导出认为如果启动后 10秒内未被执行，则认为是垃圾数据，删除掉
							 */
							if((new Date().getTime() - jobDetail.getNextfiretime().getTime()) > 10000){
								RivuDataContext.getService().deleteIObject(jobDetail) ;
								continue ;
							}
						}
						/**
						 * 1、NextFireTime 不为空  并且 CronExp不为空
						 * 2、TaskStatus 为1 （手动启动任务）
						 */
						if(((jobDetail.getNextfiretime()!=null && jobDetail.getCronexp()!=null) || RivuDataContext.TaskStatusType.READ.getType().equals(jobDetail.getTaskstatus())) || RivuDataContext.TaskStatusType.RUNNING.getType().equals(jobDetail.getTaskstatus())){
							Map<String , Object> values = new HashMap<String , Object>();
							jobDetail.setRunserver(null) ;
							values.put("job", jobDetail) ;
							/**
							 * NextFireTime在将来的 5秒内或者 TaskStatus = 1 的情况下，进入任务等待队列，如果NextFireTime时间已过，则进入到下次执行队列
							 */
							if(( RivuDataContext.TaskStatusType.READ.getType().equals(jobDetail.getTaskstatus()) || (jobDetail.getNextfiretime()!=null && jobDetail.getNextfiretime().after(new Date(System.currentTimeMillis()-5000)))) && !RivuDataContext.TaskStatusType.RUNNING.getType().equals(jobDetail.getTaskstatus())){
								/**
								 * 任务不在 等待和执行中的队列 里，从等待队列 进入执行队列的时候，需要更新任务的执行状态 和执行时间，以及执行的服务器
								 */
								if(jobDetail.getNextfiretime()==null){
									jobDetail.setNextfiretime(new Date());
								}
								jobDetail.setTaskstatus(RivuDataContext.TaskStatusType.READ.getType()) ;//进入等待执行的队列
								/**
								 * 需要均衡执行任务的服务器资源
								 */
								jobDetail.setRunserver(ClusterServerService.getRunServer()) ;
								log.info("SYSTEM/SYSTEM "+LocalTools.getMessage("I_JOBDETAIL_1000001" , values)+" SERVER:"+jobDetail.getRunserver()) ;
								
								RivuDataContext.getService().updateIObject(jobDetail);
								jobDetailMap.put(jobDetail.getId(), jobDetail) ;
							}else{
								/**
								 * 超过执行时间后未进入等待执行队列的任务，更新 NextFireTime
								 */
								try {
									if(jobDetail.getTasktype()!=null && !jobDetail.getTasktype().equals(RivuDataContext.TaskTypeEnum.EXPORT.toString())){
										/**
										 * 旧的执行时间放入 模板中
										 */
										values.put("date", jobDetail.getNextfiretime()) ;
										if(jobDetail.getCronexp()!=null){
											jobDetail.setNextfiretime(CronTools.getFinalFireTime(jobDetail.getCronexp(), new Date())) ;
										}else{
											jobDetail.setNextfiretime(new Date());
										}
										String eventMsg = LocalTools.getMessage("E_JOBDETAIL_1000001" , values) ;//放在 重置任务状态之前，记录日志的时候能够看到任务的重置前的状态
		
										jobDetail.setTaskstatus(RivuDataContext.TaskStatusType.NORMAL.getType()) ;//将任务状态重置
										RivuDataContext.getService().updateIObject(jobDetail);
										/**
										 * 创建一条事件信息，事件类型为  计划任务，记录计划任务的时间：任务创建人，任务执行时间，任务更新后的时间
										 */
										log.warn("SYSTEM/SYSTEM "+eventMsg) ;
										/**
										 * 
										 */
										DataPersistenceService.persistence(createEventBean(eventMsg , jobDetail , "E_JOBDETAIL_1000001")) ;
									}
								} catch (ParseException e) {
									log.error("SYSTEM/SYSTEM "+LocalTools.getMessage("E_JOBDETAIL_1000002" , values)) ;
								}
							}
						}
					}
				}
			}catch(Exception ex){
				ex.printStackTrace();
			}finally{
				taskRunning = false ;
			}
		}
	}
	
	/**
	 * 服务名称
	 */
	public String getName(){
		return RivuDataContext.ServiceTypeName.JOB_DETAIL.toString();
	}
}
